HAL MMC typical use cases for migration ¶
This section provides information about the HAL MMC Typical use cases for migration.
Note
The typical read and write operations—whether using polling, DMA, or interrupt (IT) modes—remain largely unchanged for the user between HAL1 and HAL2. The main difference in HAL2 is a refactored callback registration and handling model: transfer completion callbacks are now unified and event-driven, simplifying application code.
RPMB (Replay Protected Memory Block) operations also follow the same use cases as before, with only minor naming changes to APIs and parameters.
The most significant changes in HAL2 are in the linked-list DMA management. Linked-list operations now use a generic HAL Q API for node and queue management.
HAL Q is a new HAL layer introduced in HAL2 that provides advanced linked-list features shared across multiple HAL drivers. It centralizes linked-list management, improving code reuse and maintainability.
Card removal/insertion handling differs from HAL1 to HAL2:
With HAL1, in the event of card plug-in/plug-off, user should call
HAL_MMC_InitCard()upon the card insertion.With HAL2 the application calls
HAL_MMC_NotifyCardRemoval()on removal to reset the peripheral to default configuration andHAL_MMC_NotifyCardInsertion()on insertion to initialize the card and apply user configuration.
Use case: HAL MMC polling transfer mode ¶
Sequence diagram ¶
This transfer sequence in polling mode remains unchanged between HAL1 and HAL2.
Code Snippet
uint8_t Buffer_Block_Tx[BufferWordsSize], Buffer_Block_Rx[BufferWordsSize];
/* Write one block then read back (polling) */
MMC_state = HAL_MMC_Erase(&hmmc_card, BlockStartAdd, BlockEndAdd);
/* Wait for the Card Transfer status */
while(HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
if (MMC_state == HAL_OK)
{
/* Write NumberOfBlocks blocks of BufferWordsSize bytes on address BlockAddress */
MMC_state = HAL_MMC_WriteBlocks(&hmmc_card, Buffer_Block_Tx, BlockAddress, NumberOfBlocks, UserTimeout_ms);
}
else
{
Error_Handler();
}
/* Wait for the Card Transfer status before starting a read operation */
while(HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
if (MMC_state == HAL_OK)
{
/* Read NumberOfBlocks blocks of BufferWordsSize bytes from address BlockAddress */
MMC_state = HAL_MMC_ReadBlocks(&hmmc_card, Buffer_Block_Rx, BlockAddress, NumberOfBlocks, UserTimeout_ms);
}
else
{
Error_Handler();
}
/* Wait for the Card Transfer status */
while(HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
Use case: HAL MMC IT transfer mode ¶
Sequence diagram ¶
|
HAL1 |
HAL2 |
|---|---|
|
IT transfer mode uses
|
IT transfer sequence remains mostly unchanged between HAL1 and HAL2, but callback registration is unified via
|
Code Snippet
|
HAL1 |
HAL2 |
|---|---|
uint8_t Buffer_Block_Tx[BufferWordsSize];
uint8_t Buffer_Block_Rx[BufferWordsSize];
/* Register the Tx and Rx
Transfer complete callbacks */
HAL_MMC_RegisterCallback(&hmmc_card,
HAL_MMC_TX_CPLT_CB_ID,
TxCpltCallback);
HAL_MMC_RegisterCallback(&hmmc_card,
HAL_MMC_RX_CPLT_CB_ID,
RxCpltCallback);
/* Write NumberOfBlocks blocks of BufferWordsSize
bytes on address BlockAddress */
MMC_state = HAL_MMC_WriteBlocks_IT(&hmmc_card,
Buffer_Block_Tx,
BlockAddress,
NumberOfBlocks);
/* Wait for the Writing process is completed */
while(mmctransfertx == 0)
{}
/* Wait for the Card Transfer status before
starting a read operation */
while(HAL_MMC_GetCardState(&hmmc_card)
!= HAL_MMC_CARD_TRANSFER)
{}
if (MMC_state == HAL_OK)
{
/* Read NumberOfBlocks blocks of BufferWordsSize
bytes from address BlockAddress */
MMC_state = HAL_MMC_ReadBlocks_IT(&hmmc_card,
Buffer_Block_Rx,
BlockAddress,
NumberOfBlocks);
}
else
{
Error_Handler();
}
/* Wait for the Reading process is completed */
while(mmctransferrx == 0)
{}
/* Wait for the Card Transfer status before
proceeding with another MMC operation */
while(HAL_MMC_GetCardState(&hmmc_card)
!= HAL_MMC_CARD_TRANSFER)
{}
void TxCpltCallback(MMC_HandleTypeDef *hmmc) {
mmctransfertx = 1;
}
void RxCpltCallback(MMC_HandleTypeDef *hmmc) {
mmctransferrx = 1;
}
|
uint8_t Buffer_Block_Tx[BufferWordsSize];
uint8_t Buffer_Block_Rx[BufferWordsSize];
/* Register the Tx and Rx Transfer complete callbacks */
HAL_MMC_RegisterXferCpltCallback(&hmmc, MyMmcXferCallback);
/* Write NumberOfBlocks blocks of
BufferWordsSize bytes on address BlockAddress */
MMC_state = HAL_MMC_WriteBlocks_IT(&hmmc_card,
Buffer_Block_Tx,
BlockAddress,
NumberOfBlocks);
/* Wait for the Writing process is completed */
while(mmctransfertx == 0)
{}
/* Wait for the Card Transfer status
before starting a read operation */
while(HAL_MMC_GetCardState(&hmmc_card)
!= HAL_MMC_CARD_TRANSFER)
{}
if (MMC_state == HAL_OK)
{
/* Read NumberOfBlocks blocks of
BufferWordsSize bytes from address BlockAddress */
MMC_state = HAL_MMC_ReadBlocks_IT(&hmmc_card,
Buffer_Block_Rx,
BlockAddress,
NumberOfBlocks);
}
else
{
Error_Handler();
}
/* Wait for the Reading process is completed */
while(mmctransferrx == 0)
{}
/* Wait for the Card Transfer status
before proceeding with another MMC operation */
while(HAL_MMC_GetCardState(&hmmc_card)
!= HAL_MMC_CARD_TRANSFER)
{}
void MyMmcXferCallback(hal_mmc_handle_t *hmmc,
hal_mmc_event_cb_t cb_event) {
switch (cb_event) {
case HAL_MMC_EVENT_CB_TX_CPLT:
mmctransferrx = 1;
break;
case HAL_MMC_EVENT_CB_RX_CPLT:
mmctransferrx = 1;
break;
default: break;
}
}
|
Use case: HAL MMC DMA transfer mode ¶
Sequence diagram ¶
|
HAL1 |
HAL2 |
|---|---|
|
DMA transfer mode uses
|
DMA transfer sequence remains mostly unchanged between HAL1 and HAL2, but callback registration is unified via
|
Code Snippet
uint8_t Buffer_Block_Tx[BufferWordsSize], Buffer_Block_Rx[BufferWordsSize];
/* Write NumberOfBlocks blocks of BufferWordsSize bytes on address BlockAddress */
MMC_state = HAL_MMC_WriteBlocks_DMA(&hmmc_card, Buffer_Block_Tx, BlockAddress, NumberOfBlocks);
/* Wait for the Writing process is completed */
while(mmctransfertx == 0) /* The variable ``mmctransfertx`` is updated by
the callback function */
{}
/* Wait for the Card Transfer status before starting a read operation */
while(HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
if (MMC_state == HAL_OK)
{
/* Read NumberOfBlocks blocks of BufferWordsSize bytes from address BlockAddress */
MMC_state = HAL_MMC_ReadBlocks_DMA(&hmmc_card, Buffer_Block_Rx, BlockAddress, NumberOfBlocks);
}
else
{
Error_Handler();
}
/* Wait for the Reading process is completed */
while(mmctransferrx == 0) /* The variable ``mmctransferrx`` is updated by
the callback function */
{}
/* Wait for the Card Transfer status before proceeding with another MMC operation */
while(HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
Use case: HAL MMC Card RPMB management ¶
Sequence diagram ¶
RPMB operations remain largely unchanged between HAL1 and HAL2 except for renaming of APIs and parameters.
Code Snippet
|
HAL1 |
HAL2 |
|---|---|
if (HAL_MMC_SwitchPartition(&hmmc_card,
HAL_MMC_RPMB_PARTITION)
!= HAL_OK)
{
Error_Handler();
}
#if defined (RPMB_KEY_IS_NOT_YET_PROGRAMMED)
&& (RPMB_KEY_IS_NOT_YET_PROGRAMMED == 1U)
if (HAL_MMC_RPMB_ProgramAuthenticationKey(&hmmc_card,
pKey,
1000)
!= HAL_OK)
{
Error_Handler();
}
#endif /* RPMB_KEY_IS_NOT_YET_PROGRAMMED */
/*----------------- Get Write Counter ------------------*/
write_counter = HAL_MMC_RPMB_GetWriteCounter(&hmmc_card,
nonce_buffer,
1000);
/*-------------------- Generate MAC --------------------*/
/* Initialize and Init the HAL HASH Driver */
/* Compute SHA-256 digest by using the HAL HASH driver */
.
..
...
/* Wait for the Card Transfer status */
while(HAL_MMC_GetCardState(&hmmc_card)
!= HAL_MMC_CARD_TRANSFER)
{}
/*-------------- Write Authenticated data -------------*/
if (HAL_MMC_RPMB_WriteBlocks(&hmmc_card,
Buffer_tx_data,
blockadd,
numberofblocks,
mac,
5000U)
!= HAL_OK)
{
Error_Handler();
}
/*------------- Read Authenticated data ---------------*/
if (HAL_MMC_RPMB_ReadBlocks(&hmmc_card,
Buffer_rx_data,
blockadd,
numberofblocks,
nonce_buffer,
mac,
0xFFFFFFFFU)
!= HAL_OK)
{
Error_Handler();
}
/* Check the RPMB error code */
if (HAL_MMC_GetRPMBError(&hmmc_card)
!= HAL_MMC_ERROR_RPMB_OPERATION_OK)
{
Error_Handler();
}
|
if (HAL_MMC_SelectPartitionArea(&hmmc_card,
HAL_MMC_AREA_PARTITION_RPMB)
!= HAL_OK)
{
Error_Handler();
}
#if defined (RPMB_KEY_IS_NOT_YET_PROGRAMMED)
&& (RPMB_KEY_IS_NOT_YET_PROGRAMMED == 1U)
if (HAL_MMC_ProgramRPMBAuthenticationKey(&hmmc_card,
pKey,
1000)
!= HAL_OK)
{
Error_Handler();
}
#endif /* RPMB_KEY_IS_NOT_YET_PROGRAMMED */
/*--------------- Get Write Counter ----------------*/
(void)HAL_MMC_GetRPMBWriteCounter(&hmmc_card,
nonce_buffer,
&write_counter,
1000);
/*------------------ Generate MAC ------------------*/
/* Initialize and Init the HAL HASH Driver */
/* Compute SHA-256 digest by using the HAL HASH driver */
.
..
...
/* Wait for the Card Transfer status */
while(HAL_MMC_GetCardState(&hmmc_card)
!= HAL_MMC_CARD_TRANSFER)
{}
/*--------------- Write Authenticated data ------------*/
if (HAL_MMC_WriteRPMBBlocks(&hmmc_card,
Buffer_tx_data,
blockadd,
numberofblocks,
mac,
5000U)
!= HAL_OK)
{
Error_Handler();
}
/*---------------- Read Authenticated data -------------*/
if (HAL_MMC_ReadRPMBBlocks(&hmmc_card,
Buffer_rx_data,
blockadd,
numberofblocks,
nonce_buffer,
mac,
0xFFFFFFFFU)
!= HAL_OK)
{
Error_Handler();
}
/* Check the RPMB error code */
if (HAL_MMC_GetRPMBErrorCodes(&hmmc_card)
!= HAL_MMC_RPMB_OPERATION_OK)
{
Error_Handler();
}
|
Use case: HAL MMC linked-list DMA transfer ¶
Sequence diagram ¶
|
HAL1 |
HAL2 |
|---|---|
|
Linked-list DMA transfer mode uses linked list node building and insertion APIs (
|
In HAL2 linked-list DMA transfer is updated with most of linked-list management handled by HAL Q driver (A new driver provided with HAL2). The user builds nodes using
|
Code Snippet
|
HAL1 |
HAL2 |
|---|---|
/****************************************************** Build SDMMC node 1 */
MMC_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Tx[0]);
MMC_Node_Conf.BufferSize = BLOCKSIZE*1;
HAL_MMCEx_DMALinkedList_BuildNode(&MMC_N1, &MMC_Node_Conf);
/************************************************************ Build node 2 */
MMC_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Tx[BufferWordsSize]);
MMC_Node_Conf.BufferSize = BLOCKSIZE*2;
HAL_MMCEx_DMALinkedList_BuildNode(&MMC_N2, &MMC_Node_Conf);
/************************************************************ Build node 3 */
MMC_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Tx[BufferWordsSize*3]);
MMC_Node_Conf.BufferSize = BLOCKSIZE*3;
HAL_MMCEx_DMALinkedList_BuildNode(&MMC_N3, &MMC_Node_Conf);
/* Define list object */
MMC_DMALinkedListTypeDef Q_write;
/*********************************************** Connect node 1 to Queue 1 */
HAL_MMCEx_DMALinkedList_InsertNode(&Q_write, NULL, &MMC_N1);
/*********************************************** Connect node 2 to Queue 1 */
HAL_MMCEx_DMALinkedList_InsertNode(&Q_write, &MMC_N1, &MMC_N2);
/*********************************************** Connect node 3 to Queue 1 */
HAL_MMCEx_DMALinkedList_InsertNode(&Q_write, &MMC_N2, &MMC_N3);
/* Write steps */
/* Write blocks using DMA transfer with linked list */
if (HAL_MMCEx_DMALinkedList_WriteBlocks(&hmmc_card, &Q_write, 1000, 12) != HAL_OK)
{
Error_Handler();
}
/*************************************************** Wait for TX complete */
while (mmctransfertx == 0)
{}
/******************************************* Wait for card transfer state */
while (HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
/* Read steps */
MMC_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Rx[0]);
MMC_Node_Conf.BufferSize = BLOCKSIZE;
HAL_MMCEx_DMALinkedList_BuildNode(&MMC_N4, &MMC_Node_Conf);
MMC_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Rx[BufferWordsSize*2]);
MMC_Node_Conf.BufferSize = BLOCKSIZE*2;
HAL_MMCEx_DMALinkedList_BuildNode(&MMC_N5, &MMC_Node_Conf);
MMC_Node_Conf.BufferAddress = (uint32_t) &(Buffer_Rx[BufferWordsSize*3]);
MMC_Node_Conf.BufferSize = BLOCKSIZE*3;
HAL_MMCEx_DMALinkedList_BuildNode(&MMC_N6, &MMC_Node_Conf);
/* Define list object */
MMC_DMALinkedListTypeDef Q_read;
HAL_MMCEx_DMALinkedList_InsertNode(&Q_read, NULL, &MMC_N4);
HAL_MMCEx_DMALinkedList_InsertNode(&Q_read, &MMC_N4, &MMC_N5);
HAL_MMCEx_DMALinkedList_InsertNode(&Q_read, &MMC_N5, &MMC_N6);
/* Read back written block using DMA linked-list transfer */
if (HAL_MMCEx_DMALinkedList_ReadBlocks(&hmmc_card, &Q_read, 1000,12) != HAL_OK)
{
Error_Handler();
}
/*********************************************** Wait for RX/TX complete */
while (mmctransferrx == 0)
{}
/****************************************** Wait for card transfer state */
while (HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
|
/**************************************************** Build SDMMC node 1 */
HAL_MMC_FillNodeConfig(&MMC_N1, &(Buffer_Tx[0]), 1 * BLOCKSIZE);
/********************************************************** Build node 2 */
HAL_MMC_FillNodeConfig(&MMC_N2, &(Buffer_Tx[BufferWordsSize]), 2 * BLOCKSIZE);
/********************************************************** Build node 3 */
HAL_MMC_FillNodeConfig(&MMC_N3, &(Buffer_Tx[BufferWordsSize * 3]), 3 * BLOCKSIZE);
/************************************************** HAL Q initialization */
hal_q_t Q_write;
HAL_Q_Init(&Q_write, &HAL_MMC_DescOps);
/********************************************* Connect node 1 to Queue 1 */
HAL_Q_InsertNode(&Q_write, NULL, &MMC_N1);
/********************************************* Connect node 2 to Queue 1 */
HAL_Q_InsertNode(&Q_write, &MMC_N1, &MMC_N2);
/********************************************* Connect node 3 to Queue 1 */
HAL_Q_InsertNode(&Q_write, &MMC_N2, &MMC_N3);
/* Write steps */
/* Write blocks using DMA transfer with linked list */
if ((MMC_state = HAL_MMC_WriteBlocks_LinkedList(&hmmc_card, 1000, 12, &Q_write)) != HAL_OK)
{
Error_Handler();
}
/************************************************** Wait for TX complete */
while(mmctransfertx == 0)
{}
/************************************* Wait for the Card Transfer status */
while(HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
/* Read steps */
HAL_MMC_FillNodeConfig(&MMC_N4, &(Buffer_Rx[0]), 1 * BLOCKSIZE);
HAL_MMC_FillNodeConfig(&MMC_N5, &(Buffer_Rx[BufferWordsSize*2]), 2 * BLOCKSIZE);
HAL_MMC_FillNodeConfig(&MMC_N6, &(Buffer_Rx[BufferWordsSize*3]), 3 * BLOCKSIZE);
/************************************************** HAL Q initialization */
hal_q_t Q_read;
HAL_Q_Init(&Q_read, &HAL_MMC_DescOps);
HAL_Q_InsertNode(&Q_read, NULL, &MMC_N4);
HAL_Q_InsertNode(&Q_read, &MMC_N4, &MMC_N5);
HAL_Q_InsertNode(&Q_read, &MMC_N5, &MMC_N6);
/* Read back written block using DMA linked-list transfer */
if (HAL_MMC_ReadBlocks_LinkedList(&hmmc_card, 1000, 12, &Q_read) != HAL_OK)
{
Error_Handler();
}
/*********************************************** Wait for RX/TX complete */
while ((mmctransferrx == 0))
{}
/****************************************** Wait for card transfer state */
while(HAL_MMC_GetCardState(&hmmc_card) != HAL_MMC_CARD_TRANSFER)
{}
|
Use case: HAL MMC card removal/insertion handling ¶
Sequence diagram ¶
Card presence is typically monitored using a dedicated Card Detect (CD) GPIO pin, with EXTI interrupts used to notify the application of insertion or removal events.
|
HAL1 |
HAL2 |
|---|---|
|
In HAL1, upon card removal (detected via EXTI), if there is any ongoing processes (read/write) the application should stop them (for instance stop transfers with
|
In HAL2, the application similarly handles EXTI notifications. On removal, it aborts ongoing processes in the same way but also calls
|
Code Snippet
|
HAL1 |
HAL2 |
|---|---|
volatile uint8_t card_present = 0;
/* Example guarded I/O */
void USER_MMC_Application_routine()
{
if (card_present)
{
/* Perform read/write only if card is present */
/* ... */
}
}
/* EXTI callback hooked to the MMC card-detect GPIO pin */
void USER_MMC_HotPlugCallback()
{
if (USER_MMC_READ_DETECT_PIN())
{
/* Card removed */
card_present = 0U;
/* Abort ongoing processes*/
User_MMC_StopOngoingProcess(&hmmc_card);
}
else
{
/* Card inserted */
HAL_MMC_InitCard(&hmmc_card);
card_present = 1U;
}
}
|
volatile uint8_t card_present = 0;
/* Example guarded I/O */
void USER_MMC_Application_routine()
{
if (card_present)
{
/* Perform read/write only if card is present */
/* ... */
}
}
/* EXTI callback hooked to the MMC card-detect GPIO pin */
void USER_MMC_HotPlugCallback()
{
if (USER_MMC_READ_DETECT_PIN())
{
/* Card removed */
card_present = 0U;
/* Abort ongoing processes*/
USER_MMC_StopOngoingProcess(&hmmc_card);
HAL_MMC_NotifyCardRemoval(&hmmc_card);
}
else
{
/* Card inserted */
HAL_MMC_NotifyCardInsertion(&hmmc_card, &user_config);
card_present = 1U;
}
}
|